using System.Text;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using UniversalAdminSystem.Application.AIQuestions.Interfaces;
using UniversalAdminSystem.Domian.FileStorage.ValueObjects;
using UniversalAdminSystem.Domian.knowledge.Aggregates;
using UniversalAdminSystem.Domian.knowledge.IRepository;
using UniversalAdminSystem.Domian.knowledge.ValueObj;
using UniversalAdminSystem.Domian.UserConversations.Aggregates;
using UniversalAdminSystem.Domian.UserConversations.IRepository;
using UniversalAdminSystem.Infrastructure.Configs;

namespace UniversalAdminSystem.Infrastructure.Services;

public class AnswerService : IAnswerService
{
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly IMessageRepository _messageRepo;
    private readonly IDocumentChunkRepository _docChunkRepo;

    public AnswerService(IServiceScopeFactory scopeFactory, IMessageRepository messageRepo, IDocumentChunkRepository docChunkRepo)
    {
        _scopeFactory = scopeFactory;
        _messageRepo = messageRepo;
        _docChunkRepo = docChunkRepo;
    }

    public async Task<string> AnswerAsync(string userInput, IEnumerable<Message>? messages)
    {
        using var scope = _scopeFactory.CreateScope();
        var spacy = scope.ServiceProvider.GetRequiredService<SpaCyService>();
        var k2 = scope.ServiceProvider.GetRequiredService<K2ModelService>();
        var embedding = scope.ServiceProvider.GetRequiredService<EmbeddingService>();

        System.Console.WriteLine($"用户输入参数：{userInput}");
        
        // 1. 解析用户输入
        var parsedUserInput = await spacy.ParseUserInputAsync(userInput);
        System.Console.WriteLine($"用户输入解析：{parsedUserInput}");
        var parsedUserInputJson = JsonSerializer.Serialize(parsedUserInput, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
        System.Console.WriteLine($"用户输入解析结果：{parsedUserInputJson}");

        // 2. 让 K2 进行分片
        var chunksText = await k2.SendChunkingRequestAsync(parsedUserInputJson);

        // 3. 向量化分片
        var userInputEmbeddings = await embedding.GetEmbeddingAsync(chunksText);
        
        System.Console.WriteLine($"向量化：{userInputEmbeddings.Count}");

        // 4. 相似文档检索（并行）
        var allChunks = new List<DocumentChunk>();

        var retrievalTasks = userInputEmbeddings.Select(async vec =>
        {
            System.Console.WriteLine("查询文档开始");
            var publicDocs = await _docChunkRepo.FindSimilarDocumentsAsync(TextEmbedding.Create(vec), FileAccessLevel.Public);
            System.Console.WriteLine($"公开文档数：{publicDocs.Count()}");
            var restrictedDocs = await _docChunkRepo.FindSimilarDocumentsAsync(TextEmbedding.Create(vec), FileAccessLevel.Restricted);
            System.Console.WriteLine($"受限文档数：{publicDocs.Count()}");
            return publicDocs.Concat(restrictedDocs);
        });

        

        var retrievedResults = await Task.WhenAll(retrievalTasks);
        allChunks.AddRange(retrievedResults.SelectMany(r => r));

        System.Console.WriteLine($"文档检索条数:{allChunks.Count}");

        // 5. 重排文档
        var sortedChunks = allChunks
            .Where(c => !string.IsNullOrWhiteSpace(c.Content))
            .OrderByDescending(chunk => chunk.SimilarityScore)
            .Distinct()
            .ToList();

        // 6. 构造增强 Prompt（取前 N 个最相关文档）
        var topContext = string.Join("\n\n", sortedChunks.Take(5).Select(c => c.Content));

        var systemPrompt = $@"你是一个具有超长记忆的语言大师，你的名字叫做初音未来。请基于以下参考文档内容和用户问题，精准、详细地回答问题。现在是 {DateTime.Now:yyyy/MM/dd HH:mm:ss dddd}, 参考文档：{topContext}".Trim();

        // 7. 构造对话消息
        List<K2Message> chatMessages;
        if (messages != null && messages.Any())
        {
            System.Console.WriteLine("列表为不为空");
            System.Console.WriteLine($"输入消息列表为:{messages}");
            chatMessages = messages.Select(m => new K2Message
            {
                Role = m.Role,
                Content = m.Content
            }).ToList();
            System.Console.WriteLine($"输出消息列表为:{chatMessages}");
            chatMessages.Insert(0, new K2Message { Role = "system", Content = systemPrompt });
        }
        else
        {
            System.Console.WriteLine("列表为为空");
            chatMessages = new List<K2Message>
            {
                new K2Message { Role = "system", Content = systemPrompt },
                new K2Message { Role = "user", Content = userInput }
            };
        }

        // 8. 调用 K2 模型并接收流式结果
        var sb = new StringBuilder();
        await foreach (var chunk in k2.SendChatRequestAsync(chatMessages))
        {
            sb.Append(chunk);
        }

        return sb.ToString();
    }

}